{ open Parser }

rule token = parse
    [' ' '\t' '\r' '\n']	 { token lexbuf } (* Whitespace *)
  | "/*"      	   		 { block_comment lexbuf }           (* Comments *)
  | "//"     			 { line_comment lexbuf }
    (* Tokens *)
  | '('				 { LPAREN }
  | ')'      			 { RPAREN }
  | '{'      			 { LBRACE }
  | '}'      			 { RBRACE }
  | '['      			 { LSBRACE }
  | ']'      			 { RSBRACE }
  | ';'      			 { SEMI }
  | ','      			 { COMMA }
  | "++"     			 { PLUSPLUS}
  | "--"     			 { MINUSMINUS}
  | "=="     			 { EQ }
  | "!="     			 { NE }
  | "<="     			 { LE }
  | ">="     			 { GE }
  | "&&"     			 { AND }
  | "||"     			 { OR }
  | '+'      			 { PLUS }
  | '-'      			 { MINUS }
  | '*'      			 { TIMES }
  | '/'      			 { DIVIDE }
  | '%'      			 { MOD }
  | "+="      			 { PLUS_ASSIGN }
  | "-="      			 { MINUS_ASSIGN }
  | "*="      			 { TIMES_ASSIGN }
  | "/="      			 { DIVIDE_ASSIGN }
  | "%="      			 { MOD_ASSIGN }
  | '='      			 { ASSIGN }
  | '<'      			 { LT }
  | '>'      			 { GT }
  | '!'      			 { NOT }
  | '.'      			 { DOT }
    (* reserved keywords *)
    (* primitive data types *)
  | "int"			 { INT }
  | "double" 			 { DOUBLE }
  | "string" 			 { STRING } (* XINAN: to use C++ string type *)
  | "list"   			 { LIST }   (* to use C++ STL vector *)
  | "point"  			 { POINT }  (* XINAN: point with a radius *)
  | "shape"  			 { SHAPE }  (* Polygon *)
  | "image"  			 { IMAGE } (* XINAN: probably a file descriptor pointed to a bitmap image *)
  | "struct" 			 { STRUCT } (* Same as C *)
    (* keywords for control flow *)
  | "if"     	    	    	 { IF }
  | "else"   			 { ELSE }
  | "for"   			 { FOR }
  | "return" 			 { RETURN }
  | "break"  			 { BREAK }
    (* constant *)
  | ['0'-'9']+ as lxm		 { CONST_INT(int_of_string lxm) } (*integers*)
  | ['-']? ['0'-'9']+ '.' ['0'-'9']+ ('e' ['-']? ['0'-'9']+)? as lxm { CONST_DBL(float_of_string lxm) }
  | ['a'-'z' 'A'-'Z' ]['a'-'z' 'A'-'Z' '0'-'9' '_']* as lxm { ID(lxm) }
  | eof      	     	         { EOF }
  | ['.']['0'-'9']* as float 	 { raise (Failure("No support for float type " ^ float)) }
  | '"' ( [^ '\\' '"' '\n']|'\\' _ )* '"' as lxm { CONST_STR(lxm) }
  | _ as char 	       		 { raise (Failure("illegal character " ^ Char.escaped char)) }                                      

and block_comment = parse
    "*/"			 { token lexbuf }
  | _  				 { block_comment lexbuf } 

and line_comment = parse
    '\n'			 { token lexbuf }
  | _  				 { line_comment lexbuf }

(*

and const_string temp_str = parse
(* XINAN: not sure whether this will work *)
  | '"' 			 { CONST_STR(temp_str); token lexbuf }
   '\\'    	     	   	 { escape_character temp_str lexbuf }
  | [^ '\\' '\"']* as lxm   	 { const_string (temp_str ^ lxm) lexbuf	}

and escape_character temp_str = parse
  | '\\' 	      	 { const_string (temp_str ^ "\\") lexbuf }
  | 'n'       	 	 { const_string (temp_str ^ "\n") lexbuf }
  | 'r' 			 { const_string (temp_str ^ "\r") lexbuf }
  | 't' 			 { const_string (temp_str ^ "\t") lexbuf }
  | '\"'			 { const_string (temp_str ^ "\"") lexbuf }
  | _ 				 { const_string temp_str lexbuf}

  *)
